home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
151-175
/
169
/
src
/
shell
/
sub.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-13
|
12KB
|
556 lines
/*
* SUB.C
*
* (C)Copyright 1987 Matthew Dillon, All rights reserved
*
* Subroutines used throughout the shell (not very descriptive, am I?)
*/
#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include "shell.h"
#define HM_STR 0 /* various HISTORY retrieval modes */
#define HM_REL 1
#define HM_ABS 2
extern struct FileLock *Lock(), *DupLock(), *CurrentDir();
extern struct FileLock *Clock;
seterr()
{
char buf[32];
int stat;
sprintf(buf, "%ld", Lastresult);
set_var(LEVEL_SET, V_LASTERR, buf);
stat = atoi(get_var(LEVEL_SET, V_STAT));
if (stat < Lastresult)
stat = Lastresult;
sprintf(buf, "%ld", stat);
set_var(LEVEL_SET, V_STAT, buf);
}
char *
next_word(str)
register char *str;
{
while (*str && *str != ' ' && *str != 9)
++str;
while (*str && (*str == ' ' || *str == 9))
++str;
return (str);
}
char *
compile_av(av, start, end)
short start, end;
char **av;
{
char *cstr;
short i, len;
len = 0;
for (i = start; i < end; ++i)
len += strlen(av[i]) + 1;
cstr = malloc(len + 1);
*cstr = '\0';
for (i = start; i < end; ++i) {
strcat (cstr, av[i]);
strcat (cstr, " ");
}
return (cstr);
}
/*
* FREE(ptr) --frees without actually freeing, so the data is still good
* immediately after the free.
*/
Free(ptr)
char *ptr;
{
static char *old_ptr;
if (old_ptr)
free (old_ptr);
old_ptr = ptr;
}
/*
* Add new string to history (H_head, H_tail, H_len,
* S_histlen
*/
add_history(str)
char *str;
{
register struct HIST *hist;
while (H_len > S_histlen)
del_history();
hist = (struct HIST *)malloc (sizeof(struct HIST));
if (H_head == NULL) {
H_head = H_tail = hist;
hist->next = NULL;
} else {
hist->next = H_head;
H_head->prev = hist;
H_head = hist;
}
hist->prev = NULL;
hist->line = malloc (strlen(str) + 1);
strcpy (hist->line, str);
++H_len;
}
del_history()
{
if (H_tail) {
--H_len;
++H_tail_base;
free (H_tail->line);
if (H_tail->prev) {
H_tail = H_tail->prev;
free (H_tail->next);
H_tail->next = NULL;
} else {
free (H_tail);
H_tail = H_head = NULL;
}
}
}
char *
last_history_entry()
{
if (H_head)
return(H_head->line);
return("");
}
char *
get_history(ptr)
char *ptr;
{
register struct HIST *hist;
register short len;
short mode = HM_REL;
long num = 1;
char *str;
char *result = NULL;
if (ptr[1] >= '0' && ptr[1] <= '9') {
mode = HM_ABS;
num = atoi(&ptr[1]);
goto skip;
}
switch (ptr[1]) {
case '!':
break;
case '-':
num += atoi(&ptr[2]);
break;
default:
mode = HM_STR;
str = ptr + 1;
break;
}
skip:
switch (mode) {
case HM_STR:
len = strlen(str);
for (hist = H_head; hist; hist = hist->next) {
if (strncmp(hist->line, str, len) == 0 && *hist->line != '!') {
result = hist->line;
break;
}
}
break;
case HM_REL:
for (hist = H_head; hist && num--; hist = hist->next);
if (hist)
result = hist->line;
break;
case HM_ABS:
len = H_tail_base;
for (hist = H_tail; hist && len != num; hist = hist->prev, ++len);
if (hist)
result = hist->line;
break;
}
if (result) {
Eputs (result);
return(result);
}
Eputs ("History substitution failed");
return ("");
}
replace_head(str)
char *str;
{
if (str == NULL)
str = "";
if (H_head) {
free (H_head->line);
H_head->line = malloc (strlen(str)+1);
strcpy (H_head->line, str);
}
}
perror(str)
char *str;
{
ierror(str, IoErr());
}
ierror(str, err)
register char *str;
short err;
{
register struct PERROR *per = Perror;
if (err) {
for (; per->errstr; ++per) {
if (per->errnum == err) {
fhprintf (Cerr, "%s%s%s\n",
per->errstr,
(str) ? ": " : "",
(str) ? str : ""
);
return(err);
}
}
fhprintf (Cerr, "Unknown DOS error %ld %s\n", err, (str) ? str : "");
}
return (err);
}
/*
* Disk directory routines
*
* dptr = dopen(name, stat)
* struct DPTR *dptr;
* char *name;
* int *stat;
*
* dnext(dptr, name, stat)
* struct DPTR *dptr;
* char **name;
* int *stat;
*
* dclose(dptr) -may be called with NULL without harm
*
* dopen() returns a struct DPTR, or NULL if the given file does not
* exist. stat will be set to 1 if the file is a directory. If the
* name is "", then the current directory is openned.
*
* dnext() returns 1 until there are no more entries. The **name and
* *stat are set. *stat = 1 if the file is a directory.
*
* dclose() closes a directory channel.
*
*/
struct DPTR *
dopen(name, stat)
char *name;
register int *stat;
{
register struct DPTR *dp;
*stat = 0;
dp = (struct DPTR *)malloc(sizeof(struct DPTR));
if (*name == '\0')
dp->lock = DupLock (Clock);
else
dp->lock = Lock (name, ACCESS_READ);
if (dp->lock == NULL) {
free (dp);
return (NULL);
}
dp->fib = (struct FileInfoBlock *)
AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC);
if (!Examine (dp->lock, dp->fib)) {
perror (name);
dclose (dp);
return (NULL);
}
if (dp->fib->fib_DirEntryType >= 0)
*stat = 1;
return (dp);
}
dnext(dp, pname, stat)
register struct DPTR *dp;
char **pname;
int *stat;
{
if (dp == NULL)
return (0);
if (ExNext (dp->lock, dp->fib)) {
*stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1;
*pname = dp->fib->fib_FileName;
return (1);
}
return (0);
}
dclose(dp)
register struct DPTR *dp;
{
if (dp == NULL)
return (1);
if (dp->fib)
FreeMem (dp->fib, sizeof(*dp->fib));
if (dp->lock)
UnLock (dp->lock);
free (dp);
return (1);
}
isdir(file)
char *file;
{
register struct DPTR *dp;
int stat;
stat = 0;
if (dp = dopen (file, &stat))
dclose(dp);
return (stat == 1);
}
free_expand(av)
register char **av;
{
register char **base = av;
if (av) {
while (*av) {
free (*av);
++av;
}
free (base);
}
}
/*
* EXPAND(wild_name, pac)
* wild_name - char * (example: "df0:*.c")
* pac - int * will be set to # of arguments.
*
* Standalone, except in requires Clock to point to the Current-Directory
* lock.
*/
char **
expand(base, pac)
char *base;
int *pac;
{
register char *ptr;
char **eav = (char **)malloc (sizeof(char *));
short eleft, eac;
char *name;
char *bname, *ename, *tail;
int stat, scr;
register struct DPTR *dp;
*pac = eleft = eac = 0;
base = strcpy(malloc(strlen(base)+1), base);
for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr);
for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr);
if (ptr < base) {
bname = strcpy (malloc(1), "");
} else {
scr = ptr[1];
ptr[1] = '\0';
bname = strcpy (malloc(strlen(base)+1), base);
ptr[1] = scr;
}
ename = ptr + 1;
for (ptr = ename; *ptr && *ptr != '/'; ++ptr);
scr = *ptr;
*ptr = '\0';
tail = (scr) ? ptr + 1 : NULL;
if ((dp = dopen (bname, &stat)) == NULL || stat == 0) {
free (bname);
free (base);
free (eav);
Eputs ("Could not open directory");
return (NULL);
}
while (dnext (dp, &name, &stat)) {
if (compare_ok(ename, name)) {
if (tail) {
int alt_ac;
char *search, **alt_av, **scrav;
struct FileLock *lock;
if (!stat) /* expect more dirs, but this not a dir */
continue;
lock = CurrentDir (Clock = dp->lock);
search = malloc(strlen(name)+strlen(tail)+2);
strcpy (search, name);
strcat (search, "/");
strcat (search, tail);
scrav = alt_av = expand (search, &alt_ac);
CurrentDir (Clock = lock);
if (scrav) {
while (*scrav) {
if (eleft < 2) {
char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
bmov (eav, scrav, (eac + 1) << 2);
free (eav);
eav = scrav;
eleft = 10;
}
eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1);
strcpy(eav[eac], bname);
strcat(eav[eac], *scrav);
free (*scrav);
++scrav;
--eleft, ++eac;
}
free (alt_av);
}
} else {
if (eleft < 2) {
char **scrav = (char **)malloc(sizeof(char *) * (eac + 10));
bmov (eav, scrav, (eac + 1) << 2);
free (eav);
eav = scrav;
eleft = 10;
}
eav[eac] = malloc (strlen(bname)+strlen(name)+1);
eav[eac] = strcpy(eav[eac], bname);
strcat(eav[eac], name);
--eleft, ++eac;
}
}
}
dclose (dp);
*pac = eac;
eav[eac] = NULL;
free (bname);
free (base);
if (eac)
return (eav);
free (eav);
return (NULL);
}
/*
* Compare a wild card name with a normal name
*/
#define MAXB 8
compare_ok(wild, name)
char *wild, *name;
{
register char *w = wild;
register char *n = name;
char *back[MAXB][2];
register char s1, s2;
register short bi = 0;
while (*n || *w) {
switch (*w) {
case '*':
if (bi == MAXB) {
Eputs ("Too many levels of '*'");
return (0);
}
back[bi][0] = w;
back[bi][1] = n;
++bi;
++w;
continue;
goback:
--bi;
while (bi >= 0 && *back[bi][1] == '\0')
--bi;
if (bi < 0)
return (0);
w = back[bi][0] + 1;
n = ++back[bi][1];
++bi;
continue;
case '?':
if (!*n) {
if (bi)
goto goback;
return (0);
}
break;
default:
s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
if (s1 != s2) {
if (bi)
goto goback;
return (0);
}
break;
}
if (*n) ++n;
if (*w) ++w;
}
return (1);
}
Oputs(str)
char *str;
{
Write (Cout, str, strlen(str));
Write (Cout, "\n", 1);
}
Eputs(str)
char *str;
{
Write (Cerr, str, strlen(str));
Write (Cerr, "\n", 1);
}
char *
Ogets(str)
char *str;
{
register int i = 0;
while (Read(Cin, str + i, 1) == 1) {
if (str[i] == '\n') {
str[i] = 0;
return (str);
}
if (++i == 255) {
str[i] = 0;
return (str);
}
}
return (NULL);
}